#include "Message_Processing.h"
uint16 DCD_TLV_Table[256];
void Init_DCD_TLV_TABLE()
{
	DCD_TLV_Table[2]  =L_01002_BSEIRP;     
	DCD_TLV_Table[6]  =L_01006_CH_NUM;     
	DCD_TLV_Table[7]  =L_01007_TTG;        
	DCD_TLV_Table[8]  =L_01008_RTG;        
	DCD_TLV_Table[9]  =L_01009_EIRxP;      
	DCD_TLV_Table[10] =L_01010_CWFNUM;    
	DCD_TLV_Table[12] =L_01012_FREQ;      
	DCD_TLV_Table[13] =L_01013_BSID;      
	DCD_TLV_Table[17] =L_01017_HAD;       
	DCD_TLV_Table[148]=L_01148_MACVER;   
	DCD_TLV_Table[20] =L_01020_MAX_RETRAN;
	DCD_TLV_Table[21] =L_01021_RSSI_CINR; 
}


Msg_BP *Get_Msg_BP()
{
	Msg_BP *p;
	p = (Msg_BP *)malloc(sizeof(Msg_BP));
	if(p == NULL)
	{
		printf("run out of memory");
		exit(1);
	}
	return(p);
}
void Append_Msg_BP(Msg_BP **ptr,uint16 diuc ,uint16 BP)
{
	Msg_BP *newnode;
	Msg_BP *head;

	newnode = Get_Msg_BP();
	newnode->type=1;//default
	newnode->len=8; //default
	newnode->DIUC=diuc;
	newnode->BurstProfile=BP;
	newnode->next=NULL;
	head = *ptr;
	if(*ptr==NULL)
	{
		newnode->next=NULL;
		*ptr = newnode;
	}
	else
	{
		while((*ptr)->next!=NULL)
			*ptr=(*ptr)->next;
		(*ptr)->next=newnode;
		*ptr = head;
	}
}



void Init_Msg_DCD_TLV(Msg_TLV **dcd_tlv_pp)
{
	AppendTLV(dcd_tlv_pp, 7,DCD_TLV_Table,5);
	AppendTLV(dcd_tlv_pp, 8,DCD_TLV_Table,0x6);
	AppendTLV(dcd_tlv_pp,12,DCD_TLV_Table,0x5);
	AppendTLV(dcd_tlv_pp,20,DCD_TLV_Table,0x4);
	AppendTLV(dcd_tlv_pp,21,DCD_TLV_Table,0x1);
}
void Init_DBP(Msg_BP **BP_pp)
{
	//intitial DIUC mapping to DL burst profile
	Append_Msg_BP(BP_pp,  1 , 1 );
	Append_Msg_BP(BP_pp,  2 , 2 );
	Append_Msg_BP(BP_pp,  3 , 3 );
	Append_Msg_BP(BP_pp,  4 , 4 );
	Append_Msg_BP(BP_pp,  5 , 5 );
	Append_Msg_BP(BP_pp,  6 , 6 );
	Append_Msg_BP(BP_pp,  7 , 7 );
	Append_Msg_BP(BP_pp,  8 , 8 );
	Append_Msg_BP(BP_pp,  9 , 9 );
	Append_Msg_BP(BP_pp, 10 ,10 );
	Append_Msg_BP(BP_pp, 11 ,11 );
	Append_Msg_BP(BP_pp, 12 ,12 );
}
void Acc_DCD_TLV(DCD *dcd)
{
	uint16 length=0;
	Msg_TLV *tmp_p;
	tmp_p = dcd->DCD_TLV_p;
	do{
	length = (uint16)(length + dcd->DCD_TLV_p->len);//indicate the value length
	length += 2; //including type and length bytes
	dcd->DCD_TLV_p = dcd->DCD_TLV_p->next;
	}while(dcd->DCD_TLV_p!=NULL);
	dcd->DCD_TLV_p = tmp_p;
	dcd->TLV_bytes = length ;
}
void Acc_DBP(DCD *dcd)
{
	uint16 num=0;
	Msg_BP *tmp_p;
	tmp_p = dcd->BProfile_p;
	do{
		num += 1;//including 
		dcd->BProfile_p = dcd->BProfile_p->next;
	}while(dcd->BProfile_p!=NULL);
	dcd->BProfile_p = tmp_p;
	dcd->BP_num = num ;
}

void Init_Msg_DCD(MMSG **MMsg_pp)
{
	(*MMsg_pp)      =(MMSG *)malloc(sizeof(MMSG));
	(*MMsg_pp)->dcd = (DCD *)calloc(sizeof(DCD),1);
	//Initail FCH Elements
	(*MMsg_pp)->dcd->MMType = 0x1;
	(*MMsg_pp)->dcd->CCC    = 0x2;
	Init_Msg_DCD_TLV( &(*MMsg_pp)->dcd->DCD_TLV_p);
	Init_DBP(&(*MMsg_pp)->dcd->BProfile_p);
	Acc_DCD_TLV((*MMsg_pp)->dcd);
	Acc_DBP((*MMsg_pp)->dcd);
	
}
void Form_DCD_TLV(MsgQ **MsgPtr,DCD **dcd)
{
	//Set the total bytes in TLV 
	Insert_MsgQ_DList(MsgPtr,(*dcd)->TLV_bytes,8);
	while((*dcd)->DCD_TLV_p!=NULL)
	{
		Insert_MsgQ_DList(MsgPtr,(*dcd)->DCD_TLV_p->type,8);
		Insert_MsgQ_DList(MsgPtr,(*dcd)->DCD_TLV_p->len,8);
		Insert_MsgQ_DList(MsgPtr,(*dcd)->DCD_TLV_p->value,(uint8)(*dcd)->DCD_TLV_p->len*8);
		(*dcd)->DCD_TLV_p = (*dcd)->DCD_TLV_p->next;
	}
}
void Form_DBP(MsgQ **MsgPtr,DCD **dcd)
{
	//Set the total numbers in BP
	Insert_MsgQ_DList(MsgPtr,(*dcd)->BP_num,8);
	while((*dcd)->BProfile_p!=NULL)
	{
		Insert_MsgQ_DList(MsgPtr,(*dcd)->BProfile_p->type,8);
		Insert_MsgQ_DList(MsgPtr,(*dcd)->BProfile_p->len ,8);
		Insert_MsgQ_DList(MsgPtr,0,4);//reserved
		Insert_MsgQ_DList(MsgPtr,(*dcd)->BProfile_p->DIUC,4);//DIUC
		Insert_MsgQ_DList(MsgPtr,(*dcd)->BProfile_p->BurstProfile,8);//BP
		(*dcd)->BProfile_p = (*dcd)->BProfile_p->next;
	}
}
void Form_DCD(MMSG **mmsg_pp,MsgQ **MsgPtr)
{
	Insert_MsgQ_DList(MsgPtr,(*mmsg_pp)->dcd->MMType,L_MMTYPE_1);
    Insert_MsgQ_DList(MsgPtr,0,8);
	Insert_MsgQ_DList(MsgPtr,(*mmsg_pp)->dcd->CCC,L_CCC);
	Form_DCD_TLV(MsgPtr,&(*mmsg_pp)->dcd);
    Form_DBP(MsgPtr,&(*mmsg_pp)->dcd);

}
void DeForm_DCD_TLV(BUFFER **buf_pp,DCD **dcd_pp)
{
	uint64 type = 0;
	uint64 len  = 0;
	uint64 tlv_bytes =0;
    uint64 value= 0;
	
	DeFormat2Val(buf_pp,&tlv_bytes,8);
	PrintMsgVal("DCD","total TLV bytes",(uint32)tlv_bytes);
	(*dcd_pp)->TLV_bytes = (uint16 )tlv_bytes;
	while(tlv_bytes!=0)
	{
		DeFormat2Val(buf_pp,&type,8);
		DeFormat2Val(buf_pp,&len ,8);
		DeFormat2Val(buf_pp,&value,(uint8)len*8);
		AppendTLV(&(*dcd_pp)->DCD_TLV_p, (uint16)type,DCD_TLV_Table,value);
		(tlv_bytes) -= (len+2); //including type length and value 
		PrintMsgVal("DCD","type",(uint32)type);
		PrintMsgVal("DCD","length",(uint32)len);
		PrintMsgVal("DCD","value",(uint32)value);
	}
}
void DeForm_DBP(BUFFER **buf_pp,DCD **dcd_pp)
{
	uint64 tmp=0;
	Msg_BP *BP_p=NULL;
	uint64 BP_num =0;
	
	BP_p =(Msg_BP *)malloc(sizeof(Msg_BP));
	DeFormat2Val(buf_pp,(uint64 *)&(*dcd_pp)->BP_num,8);
	BP_num = (*dcd_pp)->BP_num;
	while(BP_num!=0)
	{
		DeFormat2Val(buf_pp,(uint64 *)&BP_p->type,8);//reserved
		DeFormat2Val(buf_pp,(uint64 *)&BP_p->len ,8);//reserved
		DeFormat2Val(buf_pp,&tmp ,4);//reserved
		DeFormat2Val(buf_pp,(uint64 *)&BP_p->DIUC,4);//DIUC
		DeFormat2Val(buf_pp,(uint64 *)&BP_p->BurstProfile, 8);//DL burst profile
		Append_Msg_BP(&(*dcd_pp)->BProfile_p,BP_p->DIUC ,BP_p->BurstProfile );		
		BP_num -= 1; //including type length and value 
		PrintMsgVal("DCD","type",BP_p->type);
		PrintMsgVal("DCD","type",BP_p->len);
		PrintMsgVal("DCD","DIUC",BP_p->DIUC);
		PrintMsgVal("DCD","Burst Profile",BP_p->BurstProfile);

	}
}
void DeForm_DCD(BUFFER **buf_pp,DCD **dcd_pp)
{
	uint64 tmp;
	*dcd_pp = (DCD *)calloc(sizeof(DCD),1);
	//DeFormat2Val(buf_pp,(uint64 *)&(*dcd_pp)->MMType,L_MMTYPE_1);            
	DeFormat2Val(buf_pp,&tmp,8);
	DeFormat2Val(buf_pp,(uint64 *)&(*dcd_pp)->CCC,L_CCC);
	PrintMsg("----------","Decode DCD","----------");
	PrintMsgVal("DCD","CCC",(*dcd_pp)->CCC);
	DeForm_DCD_TLV(buf_pp,dcd_pp);
	DeForm_DBP(buf_pp,&*dcd_pp);
 }
void Compare_DCD(MMSG *mmsg_gen_p ,MMSG *mmsg_get_p)
{
	BUFFER *buf_gen_p=NULL;
	BUFFER *buf_get_p=NULL;
	MsgQ *Msg_gen_p=NULL;
	MsgQ *Msg_get_p=NULL;
	int result;

	Form_DCD(&mmsg_gen_p,&Msg_gen_p);
	buf_gen_p = FormatMsgQ2Buf(Msg_gen_p);

	Form_DCD(&mmsg_get_p,&Msg_get_p);
	buf_get_p = FormatMsgQ2Buf(Msg_get_p);
	result = memcmp (buf_get_p->buffer,buf_gen_p->buffer,buf_gen_p->bitoffset);
	printf("The compare result of DCD is %d\n",!result);

}
void Test_DCD()
{
	MsgQ *MsgPtr=NULL;
	MMSG *mmsg_gen_p=NULL;//generate
	MMSG *mmsg_ope_p=NULL;//operate
	MMSG *mmsg_get_p=NULL;//get
	BUFFER *buf_p=NULL;
	

    mmsg_get_p =(MMSG *)malloc(sizeof(MMSG));

	
	Init_MsgQ(&MsgPtr);
	Init_Buffer(&buf_p);

	Init_Msg_DCD(&mmsg_gen_p);
	Init_Msg_DCD(&mmsg_ope_p);    

	Form_DCD(&mmsg_ope_p,&MsgPtr);
	buf_p = FormatMsgQ2Buf(MsgPtr);
	buf_p->base =buf_p->buffer;
	buf_p->bitoffset=0;
	DeForm_DCD(&buf_p,&mmsg_get_p->dcd);
    Compare_DCD(mmsg_gen_p,mmsg_get_p);
}